package com.maikang.exammall.api;

import com.maikang.exammall.entity.BaseEntity;
import com.maikang.exammall.entity.dto.FindAllRequest;
import com.maikang.exammall.entity.dto.ResponseDTO;
import com.maikang.exammall.service.BaseService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.server.ResponseStatusException;

import javax.validation.Valid;
import java.io.Serializable;
import java.util.Optional;

import static org.apache.commons.lang3.exception.ExceptionUtils.getMessage;

@Log4j2
public class DictionaryController<ENTITY extends BaseEntity<ID>, ID extends Serializable, SERVICE extends BaseService<ENTITY, ID, ?>> implements CrudRepository<ENTITY, ID> {

    @Autowired
    protected SERVICE service;

    @PostMapping(value = "/search")
    public ResponseDTO<Iterable<ENTITY>> findAll(@RequestBody(required = false) FindAllRequest<ENTITY> findAllRequest) {
        return ResponseDTO.ok(service.findAll());
    }

    protected Iterable<ENTITY> findAll(Example<ENTITY> example, Pageable pageable) {
        return service.findAll(example, pageable);
    }

    protected Iterable<ENTITY> findAll(Example<ENTITY> example) {
        return service.findAll(example);
    }

    @Override
    public <S extends ENTITY> S save(@Valid @RequestBody S entity) {
        throw new UnsupportedOperationException();
    }

    @Override
    public <S extends ENTITY> Iterable<S> saveAll(Iterable<S> entities) {
        throw new UnsupportedOperationException();
    }


    @Override
    @Transactional(readOnly = true)
    public Optional<ENTITY> findById(ID id) {
        try {
            return service.findById(id);
        } catch (Exception e) {
            log.error("failed to findById: " + id, e);
            throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "failed to findById: " + id + ", err: " + getMessage(e));
        }
    }

    @GetMapping("/{id}")
    @Transactional(readOnly = true)
    public ResponseDTO<ENTITY> findByIdOrNull(@PathVariable("id") ID id) {
        return ResponseDTO.ok(findById(id).orElse(null));
    }

    @Override
    public boolean existsById(@PathVariable("id") ID id) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Iterable<ENTITY> findAll() {
        throw new UnsupportedOperationException();
    }


    @Override
    public Iterable<ENTITY> findAllById(Iterable<ID> ids) {
        throw new UnsupportedOperationException();
    }


    @Override
    public long count() {
        throw new UnsupportedOperationException();
    }


    @Override
    public void deleteById(@PathVariable("id") ID id) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void delete(@RequestBody ENTITY entity) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void deleteAll(@RequestBody Iterable<? extends ENTITY> entities) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void deleteAll() {
        throw new UnsupportedOperationException();
    }
}
